"""
module organization:

0. imports
1. views
2. server related functions
3. get_app

"""

from pyramid.config import Configurator
from pyramid.events import NewRequest
from pyramid.response import Response, FileResponse


from med.views.appointments import get_appointments_view
from med.views.begin_appointment import get_begin_appointment_view
from med.views.current_user import get_current_user_view
from med.views.download import get_download_file
from med.views.entry import get_entry_view
from med.views.filters import get_filters_view
from med.views.profile import get_profile_view
from med.views.reassign import get_reassign_view
from med.views.record import get_record_view
from med.views.search import get_search_view
from med.views.update_condition import get_update_condition_view
from med.views.users import get_users_view


# ======== PAGES =====================================================
def home(request):
    return Response("OK")


def login(request):
    return Response("TODO: The login page goes here.")


# ======== SESSION ===================================================
def current_user(request):
    return get_current_user_view()


def filters(request):
    return get_filters_view()


def keep_alive(request):
    return Response("OK")


def users(request):
    return get_users_view()


# ======== REMAINING VIEWS ===========================================
# ======== APPOINTMENTS
def begin_appointment(request):
    return get_begin_appointment_view()


def reassign_appointment(request):
    return get_reassign_view()


def appointment_users(request):
    return get_users_view()


def update_condition(request):
    return get_update_condition_view()


def appointments(request):
    return get_appointments_view()


# ======== ENTRY
def entry(request):
    return get_entry_view(entry_id=request.params.get("id", None))


def reassign_entry(request):
    return {
        "status": "success",
        "reason": "",
        "errors": {},
        "testing": True,
    }


def resolve_entry(request):
    return {
        "status": "success",
        "reason": "",
        "errors": {},
        "testing": True,
    }


def add_message(request):
    return {
        "status": "success",
        "reason": "",
        "errors": {},
        "testing": True,
    }


# NOTE: Appointment data on the Entry view
def finish_appointment(request):
    return {
        "status": "success",
        "reason": "",
        "errors": {},
        "testing": True,
    }


# NOTE: Record data on the Entry view
def clear_hold(request):
    return {
        "status": "success",
        "reason": "",
        "errors": {},
        "testing": True,
    }


# ======== PROFILE
def profile(request):
    return get_profile_view()


# ======== SEARCH
def search_records(request):
    return get_search_view(search_input=request.params.get("q", None))


def intake(request):
    return {
        "status": "success",
        "reason": "",
        "errors": {},
        "testing": True,
    }


# ======== RECORDS
def record(request):
    return get_record_view(record_id=request.params.get("id", None))


def download(request):
    filepath, filename, content_type = get_download_file(
        file_id=request.params.get("id", None),
        filename=request.params.get("filename", None),
        repo=request.params.get("repo", None),
        fkey=request.params.get("fkey", None),
    )
    response = FileResponse(filepath, request=request, content_type=content_type)
    response.headers["Content-Disposition"] = f'attachment; filename="{filename}"'
    return response


def followup(request):
    return {
        "status": "success",
        "reason": "",
        "errors": {},
        "testing": True,
    }


# ======== SERVER ====================================================
def add_cors_headers_response_callback(event):
    def cors_headers(request, response):
        response.headers.update(
            {
                "Access-Control-Allow-Origin": "*",
                "Access-Control-Allow-Methods": "POST,GET,DELETE,PUT,OPTIONS",
                "Access-Control-Allow-Headers": "Origin, Content-Type, Accept, Authorization",
                "Access-Control-Allow-Credentials": "true",
                "Access-Control-Max-Age": "1728000",
            }
        )

    event.request.add_response_callback(cors_headers)


def get_app(enable_cors=False):
    with Configurator() as config:

        if enable_cors:
            config.add_subscriber(add_cors_headers_response_callback, NewRequest)

        # NOTE: Group route/view and order by route.
        config.add_route(home.__name__, "/")
        config.add_view(home, route_name=home.__name__)

        config.add_route(login.__name__, "/login")
        config.add_view(login, route_name=login.__name__)

        config.add_route(reassign_appointment.__name__, "/api/appointment/reassign")
        config.add_view(
            reassign_appointment,
            route_name=reassign_appointment.__name__,
            renderer="json",
        )

        config.add_route(begin_appointment.__name__, "/api/appointment/begin")
        config.add_view(
            begin_appointment,
            route_name=begin_appointment.__name__,
            renderer="json",
        )

        config.add_route(update_condition.__name__, "/api/appointment/checkin")
        config.add_view(
            update_condition,
            route_name=update_condition.__name__,
            renderer="json",
        )

        config.add_route(appointment_users.__name__, "/api/appointment/users")
        config.add_view(
            appointment_users,
            route_name=appointment_users.__name__,
            renderer="json",
        )

        config.add_route(appointments.__name__, "/api/appointments")
        config.add_view(
            appointments,
            route_name=appointments.__name__,
            renderer="json",
        )

        config.add_route(download.__name__, "/api/download")
        config.add_view(
            download,
            route_name=download.__name__,
            renderer="json",
        )

        config.add_route(entry.__name__, "/api/entry")
        config.add_view(
            entry,
            route_name=entry.__name__,
            renderer="json",
        )

        config.add_route(reassign_entry.__name__, "/api/entry/reassign")
        config.add_view(
            reassign_entry,
            route_name=reassign_entry.__name__,
            renderer="json",
        )

        config.add_route(resolve_entry.__name__, "/api/entry/resolve")
        config.add_view(
            resolve_entry,
            route_name=resolve_entry.__name__,
            renderer="json",
        )

        config.add_route(add_message.__name__, "/api/entry/add_message")
        config.add_view(
            add_message,
            route_name=add_message.__name__,
            renderer="json",
        )

        config.add_route(finish_appointment.__name__, "/api/entry/finish_appointment")
        config.add_view(
            finish_appointment,
            route_name=finish_appointment.__name__,
            renderer="json",
        )

        config.add_route(record.__name__, "/api/record")
        config.add_view(
            record,
            route_name=record.__name__,
            renderer="json",
        )

        config.add_route(clear_hold.__name__, "/api/record/clear_hold")
        config.add_view(
            clear_hold,
            route_name=clear_hold.__name__,
            renderer="json",
        )

        config.add_route(followup.__name__, "/api/record/followup")
        config.add_view(
            followup,
            route_name=followup.__name__,
            renderer="json",
        )

        config.add_route(intake.__name__, "/api/record/intake")
        config.add_view(
            intake,
            route_name=intake.__name__,
            renderer="json",
        )

        config.add_route(search_records.__name__, "/api/records")
        config.add_view(
            search_records,
            route_name=search_records.__name__,
            renderer="json",
        )

        config.add_route(current_user.__name__, "/api/session/user")
        config.add_view(
            current_user,
            route_name=current_user.__name__,
            renderer="json",
        )

        config.add_route(keep_alive.__name__, "/api/session")
        config.add_view(
            keep_alive,
            route_name=keep_alive.__name__,
            renderer="json",
        )

        config.add_route(filters.__name__, "/api/session/filters")
        config.add_view(
            filters,
            route_name=filters.__name__,
            renderer="json",
        )

        config.add_route(profile.__name__, "/api/user")
        config.add_view(
            profile,
            route_name=profile.__name__,
            renderer="json",
        )

        config.add_route(users.__name__, "/api/users")
        config.add_view(
            users,
            route_name=users.__name__,
            renderer="json",
        )

        return config.make_wsgi_app()
